import gulp from 'gulp'
import watch from 'gulp-watch'
import batch from 'gulp-batch'
import env from 'gulp-env'
import randomstring from 'randomstring'
import fs from 'fs'
import path from 'path'
import readline from 'readline'
import './src/utils/string-prototype'
import './src/utils/date-prototype'
import xlsx from 'xlsx'
// import crypto from 'crypto-js'
// import AES from 'crypto-js/aes'
// import crypto.enc.Utf8 from 'crypto-js/enc-utf8'
// import crypto.enc.Base64 from 'crypto-js/enc-base64'
// import Mode from 'crypto-js/mode-cfb'
// import PaddingPkcs7 from 'crypto-js/pad-pkcs7'
import browser from 'browser-sync'
import Table from './src/code/core/Table'
import Paths from './src/utils/entity/Paths'
import Aes from './src/utils/Aes'

const web = browser.create()

const options = require('minimist')(process.argv.slice(2), {})

env.set({
  ENV: 'development',
  NODE_ENV: 'development',
  VUE_APP_BASE_API: 'http://localhost:8080',
  VUE_APP_ENCRYPT_ENABLED: 'NO',
  GULPFILE: true,
  DEVELOPMENT: true,
  BROWSER: false,
  VUE_APP_AES_ENABLED: 'NO',
  VUE_APP_AES_SECRET_KEY: 'VnlSwQROeLeaZyXYqKFzdWmtsYseGwEF',
  //VUE_APP_AES_IV: '2022010100112299'
})

gulp.task('default', async() => {
})

gulp.task('test', async() => {
  await import('./src/api/http')
  // await (await import('./test/api/CommonService.test')).default.csrfToken()

  await (await import('./test/api/CodeAuthIdService.test.js')).default.testAll() // 测试代码模板接口
  await (await import('./test/api/CodeOpenIdService.test.js')).default.testAll() // 测试代码模板接口
  await (await import('./test/api/CodeSearchIdService.test.js')).default.testAll() // 测试代码模板接口
  await (await import('./test/api/OpenCodeSearchIdService.test.js')).default.testAll() // 测试代码模板接口

  await (await import('./test/api/CodeExampleService.test')).default.testAll()
  await (await import('./test/api/RoleService.test')).default.testAll() // 测试角色接口
  await (await import('./test/api/UserService.test')).default.testAll() // 测试用户相关的接口
  await (await import('./test/api/UploadService.test')).default.testAll() // 测试通用模块接口
})
gulp.task('test:one', async() => {
  await import('./src/api/http')
  // await (await import('./test/api/UploadService.test')).default.csrfToken()
  await (await import('./test/api/UserService.test')).default.loginAdminBasic()
  await (await import('./test/api/UserService.test')).default.resetPassword()

})

gulp.task('aes', async() => {
  // process.env.VUE_APP_AES_ENABLED='YES'
  // process.env.VUE_APP_AES_SECRET_KEY='VnlSwQROeLeaZyXYqKFzdWmtsYseGwEF'
  // process.env.VUE_APP_AES_IV='2022010100112299'

  Aes.setEnabled('YES')
  Aes.setSecretKey('VnlSwQROeLeaZyXYqKFzdWmtsYseGwEF')

  console.log(Aes.decrypt('MDAwMTY0NTQ0NDU1NjAwNvvAt+nSiC/vRWuvBMFPcS6XeET6qKXOcBjfBIxamR+2Mbby087PzqTg8VwhRDCEd8FEWeRYVDy54E3PPSwHKrHEYR4uPVM9dDHoymqkFyxzl++FiSzEh7ygkJdtvOpm6N4MOa0XzwJ2LzBNKsseYoWTu2oi49klTrPv58hHQ3a9jZzgpCOF9/JzZWPnaY9EYHZnqW4L214vwn5bPly3m8ynzajiDamGeGyXr3ucQaL2rVad5rGQYro94rJDS6+vXk2E8VdPEQ3rtuBm+aMepGVKN8ak+QS5L8QZ5DVB+xZQShVHQfRQc8oRVrfAmohGl3EDN8zRP0WYi4vBIb8/SOYVQjmmiyEplxvuu8hlACJlkYP9asHMFVM91j/v1jFENynw2ojUcsuF49D6S6o9c+xn3NUy7MnTI0dNwb+ZPgPxGenAR40McOqsWLpWLKJUwb4na3dvgX/6Jj9/91T9QXv34VjUmFWOkIpDDO3QshMe2667ww3Oj4LIgiEc5YzgaU4AHnwqoAciOcShHp5/g2ucyd+YbLvght3auywjSBIitFFJl3OncWgLNZXFH0dLGVcJQdTg3U9pNO5MVq+jHnS3ccJOkKWW59enXTraSiCaUIkU31PpbFbqBq6G6L4BYNUZh55mjVx+eZpU4TMRz4PXc+21CmaTyedpo7IHfLp/vTN+lNC6Wqya/Wq4HBwJ07vWZZkObXUTEa6furpnq86t43x3MpzqOEOLHjMMc/M15WkZNUCu7MaMXpO0MBAjGrXE5/WnF+9NFgACKbkRPks939GUMH5zjD7JVLO/bqK2+OXMIAASnBRjo0NevwBlz+VJhGoFsKAJzhnN+xn8OAk='))
  console.log(Aes.decrypt('MDAwMTY0NTQ0NTEyMTcwN7BEKBitso1RUr8NkziaDKLxurXEgIwSiDnIFD3/UjuVC/kxnRwX+D+txsOQbiRXbMK8GcPRzwYxpO5qN0dK2ywzwJI3xA4LBBAGar/w6TehvMvTReMUrMmE1lgyJY/LGip4f2EFrLV6JFY/VGS475kFc0N+OW8Y8BIOdVONuX84vxiS7OCWKJo2eAz/aLp+7u/SIyai7YcQ4FW5889dEOr5qhkqqmk3iWA89Ef+4dYfutf8jUsUq7RQ0oktyfAet6NsDfWVxFM4YV82Y4loXHTowlkYB0jIEpgRBoORFQ5m8YCYBlXU6dg9X7VH2p9B21vAp8MUzv5K0WkD6RE8W7gg+ViEz5DynJDqbkjReMpJ'))

  console.log(JSON.stringify(['动态 IV 加密 Aes.encrypt', Aes.encrypt('测试 js 加密')]))
  console.log(JSON.stringify(['动态 IV 解密 Aes.decrypt', Aes.decrypt('MDAwMTY0NTQ0NDYyODY0OQOK1jx9D1vA+fy4VW7f2e8od4X3klGeQx67JB/uiIMC')]))
  console.log(JSON.stringify(['动态 IV 解密 java 加密数据', Aes.decrypt('MjAyMjAyMjEwMmxsdmNVV/Dmre0Gf0fTXDb9DCxOhWM=')]))

  Aes.setIV('2022010100112299')
  console.log(JSON.stringify(['静态 IV 加密 Aes.encrypt', Aes.encrypt('测试 js 加密')]))
  console.log(JSON.stringify(['静态 IV 解密 Aes.decrypt', Aes.decrypt('/IcOIjPiIvm3oKbNISzwdonBPfcHE4vxUiP22KTXdlU=')]))
  console.log(JSON.stringify(['静态 IV 解密 java 加密数据', Aes.decrypt('QR+MoBavrFsTrzFngtx6Vg==')]))
})

/**
 * mysql sql 执行
 * @param connection
 * @param sql
 * @return {Promise<*>}
 */
const query = (connection, sql) => new Promise((resolve, reject) => {
  console.info(sql)
  connection.query(sql, (err, result) => {
    if (err) {
      console.error('[ERROR] - ', err.message)
      reject(err)
    } else {
      resolve(result)
    }
  })
})
gulp.task('db:java:code', async() => {
  const templates = [ // 模板参考
    ['tab_code_auth_id', 'AuthId.js'],
    ['tab_code_search_id', 'AuthSearchId.js'],
    ['tab_code_open_id', 'OpenId.js'],
    ['tab_code_search_id', 'OpenSearchId.js'],
  ]
  templates.forEach(([tableName, templateName]) => {
    console.log({
      table: [tableName],
      template: templateName
    })
  })

  const author = '谢长春'
  const host = 'localhost'
  const port = '3306'
  const user = 'root'
  const password = '111111'
  const database = 'demo_main_db' // 数据库名
  const table = [ // 表名
    // tableName
    'tab_code_example',
    'tab_error_log'
  ] // 表名
  const module = '../main-module' // 模块目录
  const pkg = 'com.ccx.demo' // 包名(也会作为文件输出目录)
  const model = 'JPA' // 模板引擎模式，可选值：[JPA, SQL]
  const template = 'AuthId.js' // 代码模板，表中包含以下字段：【createUserId,updateUserId,deleted】
  // const template = 'AuthSearchId.js' // 代码模板，表中包含以下字段：【createUserId,updateUserId,deleted】
  // const template = 'OpenId.js' // 代码模板，表中包含以下字段：【deleted】
  // const template = 'OpenSearchId.js' // 代码模板，表中包含以下字段：【deleted】
  // const template = templateName // 代码模板

  const mysql = require('mysql')
  console.log([{
    database,
    host,
    user,
    password,
    port,
    table,
    template,
    pkg
  }])
  const connection = mysql.createConnection({
    database,
    host,
    user,
    password,
    port
  })
  connection.connect()
  // *******************************************************************************************************************
  // for (const [tableName, template] of templates) {
  //   console.log({table: [tableName], template})
  //   const table = [tableName]

  const tables = await query(connection, `SHOW TABLE STATUS FROM ${database} where Name in ('${table.join('\',\'')}')`)
  console.table(tables)
  for (let i = 0, len = tables.length; i < len; i++) {
    const table = new Table(tables[i], model)
    const columns = await query(connection, `SHOW FULL COLUMNS FROM ${table.name}`)
    console.table(columns)
    table
      .setAuthor(author)
      .setPkg(pkg)
      .setColumns(columns)
      .setOutput(module)
    await table.writeHttp(template.replace(/\.js/, ''))
    await table.writeController(template.replace(/\.js/, ''))
    await table.writeEntity(template.replace(/\.js/, ''))
    await table.writeService(template.replace(/\.js/, ''))
    await table.writeRepository(template.replace(/\.js/, ''))
    await table.writeJsEntity(template.replace(/\.js/, ''))
    await table.writeJsService(template.replace(/\.js/, ''))
    await table.writeJsServiceTest(template.replace(/\.js/, ''))
  }
  // }
  // *******************************************************************************************************************
  connection.end()
})

gulp.task('mysql:read:write', async() => {
  // # 查看所有表定义参数，where name = '指定表名'
  // SHOW TABLE STATUS FROM demo_main_db;
  // # 查看 DDL
  // SHOW CREATE TABLE tab_code_example;
  // # 表全量信息
  // SHOW FULL COLUMNS FROM tab_code_example;
  // # 表部分信息
  // DESCRIBE tab_code_example;
  // # 查看表数据行数
  // SELECT TABLE_NAME, TABLE_ROWS FROM INFORMATION_SCHEMA.PARTITIONS WHERE TABLE_SCHEMA = 'demo_main_db'
  // SELECT * FROM information_schema.PROCESSLIST WHERE db = 'demo_main_db' ORDER BY TIME DESC;
  // SELECT t.trx_mysql_thread_id,t.* FROM information_schema.INNODB_TRX t;
  // SELECT t.THREAD_ID,t.* FROM performance_schema.threads t WHERE PROCESSLIST_ID = ${trx_mysql_thread_id};
  // SELECT * FROM performance_schema.events_statements_current WHERE THREAD_ID = ${THREAD_ID};
  const mysql = require('mysql')
  const connection = mysql.createConnection({
    host: 'localhost',
    port: '3306',
    user: 'root',
    password: '111111',
    database: 'demo_main_db'
  })
  connection.connect()
  connection.query('SELECT * FROM tab_user;',
    (err, result) => {
      if (err) {
        console.error('[SELECT ERROR] - ', err.message)
        return
      }
      const wb = xlsx.utils.book_new()
      xlsx.utils.book_append_sheet(wb, xlsx.utils.json_to_sheet(result))
      xlsx.writeFile(wb, './temp/tab_name.xlsx')
      console.table(result)
    })
  connection.end()
})
gulp.task('mysql:markdown', async() => {
  const mysql = require('mysql')
  const db = {
    host: 'localhost',
    port: '3306',
    user: 'root',
    password: '111111',
    database: 'demo_main_db'
  }
  const paths = Paths.resolve('temp/md')
  paths.rm(true)
  paths.mkdirs()
  const connection = mysql.createConnection(db)
  connection.connect()
  const tables = await query(connection, `SHOW TABLE STATUS FROM ${db.database} WHERE engine IS NOT NULL;`)
    .then(async result => {
      // console.table(result);
      return result.map(({
                           Name,
                           Engine,
                           Collation,
                           Comment
                         }) =>
        Object.assign({
          name: Name,
          engine: Engine,
          collation: Collation,
          comment: Comment
        }))
    })
  console.table(tables)
  const writer = fs.createWriteStream(path.resolve(`temp/md/${db.database}.md`))
  writer.write(`# ${db.database} 数据库说明文档

### 目录
|表名|说明|
|----|----|
`)
  for (let i = 0, len = tables.length; i < len; i++) {
    const {
      name,
      engine,
      collation,
      comment
    } = tables[i]
    writer.write(`|[${name}](#${name})|${comment || '-'}|\n`)
  }
  for (let i = 0, len = tables.length; i < len; i++) {
    const {
      name,
      engine,
      collation,
      comment
    } = tables[i]
    writer.write(`<a id="${name}" name="${name}"></a>\n`)
    writer.write(`#### ${comment || '-'}\n`)
    writer.write(`${'select * from'} ${name};\n\n`)
    { // markdown 字段表格部分
      writer.write('|序号|字段|类型|允许空|默认值|描述|\n')
      writer.write('|:----:|----|----|----|----|----|\n')
      const columns = await query(connection, `SHOW FULL COLUMNS FROM  ${name}`)
      columns.forEach(({
                         Field,
                         Type,
                         Collation,
                         Null,
                         Default,
                         Comment
                       }, index) =>
        writer.write(`|${index + 1}|${Field}|${Type}|${Null}|${Default || '-'}|${Comment || '-'}|\n`))
      // console.log(columns);
    }
    writer.write('\n\n\n')
    // { // DDL 部分
    //     writer.write('```mysql\n');
    //     const [{'Create Table': ddl}] = await query(connection, `SHOW CREATE TABLE ${name}`);
    //     // console.log([tableName, ddl]);
    //     writer.write(ddl);
    //     writer.write('\n```');
    // }
  }
  writer.end()
  connection.end()
})

gulp.task('listener', function() {
  watch('src/**/*.html', batch(function() {
    web.reload()
    gulp.start('build')
  }))
  // gulp.watch([
  //     'src/**/*.js'
  // ], function() {
  //     console.log('js');
  //     return gulp.src('src/**/*.js')
  //         .pipe(plugins.changed('dest'))
  //         .pipe(plugins.debug({title: 'scripts监听修改文件:'}))
  //         .pipe(gulp.dest('dest'))
  //         .pipe(reload({stream: true}));
  // });
  // gulp.watch('src/**/*.css', function() {
  //     console.log('css');
  //     return gulp.src('src/**/*.css')
  //         .pipe(plugins.changed('dest'))
  //         .pipe(plugins.debug({title: 'css监听修改文件:'}))
  //         .pipe(gulp.dest('dest'))
  //         .pipe(web.stream());
  // });
  return Promise.resolve()
})
gulp.task('server', gulp.series('listener', () => {
  web.init({
    // proxy: 'http://localhost/index.html'
    server: {
      baseDir: 'src/',
      index: 'index.html'
    }
  })
}))

gulp.task('in:out', async() => {
  const writer = fs.createWriteStream(path.resolve('temp/out.txt'))
  writer.on('close', () => console.log('end'))
  readline.createInterface(
    fs.createReadStream(path.resolve('temp/in.txt')),
    writer
  )
    .on('line', line => {
      writer.write(line.concat(',\n'))
    })
    .on('close', () => writer.end())
})
gulp.task('write:line', async() => {
  const writer = fs.createWriteStream(path.resolve('temp/test.log'))
  writer.on('close', () => console.log('end'))
  writer.write('测试\n')
  writer.write('测试\n')
  writer.write('测试\n')
  writer.end()
})
gulp.task('read:line', async() => {
  readline.createInterface(fs.createReadStream(path.resolve('temp/test.log')))
    .on('line', text => {
      console.log(text)
    })
    .on('close', () => console.log('end'))
})

gulp.task('xlsx:read', async() => {
  const wb = xlsx.readFile(
    './temp/数据文件.xls'
  )
  const file = 'temp/数据文件.sql'
  const writer = fs.createWriteStream(file)
  writer.on('close', () => console.log(path.resolve(file)))
  const sheet = wb.Sheets[wb.SheetNames.shift()]
  // const sheet = wb.Sheets['SQL Results']
  sheet['!ref'] = sheet['!ref'].replace(/\w+:(\w+)/, 'B1:$1')
  const arrs = xlsx.utils.sheet_to_json(sheet)
    .map(row => {
      _.forEach(row, (v, k) => {
        if (v === '') delete row[k]
      })
      writer.write(
        `${Object.values(row).join(',')}\n`
      )
      return row
    })

  writer.end()
})
gulp.task('xlsx:write', async() => {
  const {data: {errorInfos: array}} = JSON.parse('')
  array.sort((a, b) => a.rowNumber - b.rowNumber)
  const wb = xlsx.utils.book_new()
  xlsx.utils.book_append_sheet(wb, xlsx.utils.json_to_sheet(array), 'Sheet1')
  xlsx.writeFile(wb, './temp/write.xlsx')
})

gulp.task('exec', async() => {
  const proc = require('child_process')
  proc.exec('ls', function(error, stdout, stderr) {
    console.log(stdout)
    if (error !== null) {
      console.log('exec error: ' + error)
    }
  })
})

gulp.task('stdout', async() => {
  process.stdin.setEncoding('utf8')
  process.stdin.on('readable', () => {
    const chunk = process.stdin.read()
    if (chunk) {
      process.stdout.write(`data: ${chunk}`)
      process.exitCode = 1
    }
  })
  process.stdin.on('end', () => {
    process.stdout.write('end')
  })
})

gulp.task('randomstring:test', async() => {
  for (let i = 0; i < 100; i++) {
    console.log(randomstring.generate())
  }
})

gulp.task('replace:swagger:order:position', async() => {
  const path = ''
  if (!path) return
  let index = 1
  fs.writeFileSync(path, fs.readFileSync(path).toString().replace(/(position = )\d+/g, (m, $1) => `${$1}${index++}`))
})
